#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
图形用户界面 - 批量提取工具的GUI界面
提供用户友好的图形界面进行批量数据提取
"""

import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import os
import threading
from datetime import datetime
from pathlib import Path
import logging
import sys

from app.batch_processor import BatchProcessor
from app.config import APP_SETTINGS
from utils.helpers import open_file_explorer, is_valid_quarter_format, parse_quarters


class ExtractorGUI:
    """批量提取器GUI类"""
    
    def __init__(self, root):
        """初始化GUI
        
        Args:
            root: tkinter根窗口
        """
        self.root = root
        self.setup_window()
        self.setup_logging()
        
        # 设置变量
        self.data_dir_var = tk.StringVar()
        self.time_range_var = tk.StringVar(value="2025Q1-2025Q2")
        self.result_dir_var = tk.StringVar()
        
        # 验证状态变量
        self.validation_status = tk.StringVar(value="")
        self.is_valid = False
        
        # 创建界面
        self.create_widgets()
        self.set_default_values()
        
    def setup_window(self):
        """设置窗口属性"""
        gui_settings = APP_SETTINGS['GUI_SETTINGS']
        
        self.root.title(gui_settings['TITLE'])
        self.root.geometry(gui_settings['WINDOW_SIZE'])
        self.root.resizable(True, True)
        self.root.minsize(*gui_settings['MIN_SIZE'])
    
    def setup_logging(self):
        """设置详细日志"""
        # 设置根日志级别
        logging.basicConfig(
            level=logging.DEBUG,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.StreamHandler(sys.stdout),  # 输出到控制台
                logging.FileHandler('word_extractor_debug.log', encoding='utf-8')  # 保存到文件
            ]
        )
        
        # 获取日志器
        self.logger = logging.getLogger('ExtractorGUI')
        self.logger.info("启动GUI，开始详细日志记录")
        
        print("=== 详细日志已启用 ===")
        print("日志将输出到控制台和 word_extractor_debug.log 文件")
        print("追踪目标任务: JL252001, JL252701, JL252002, JL252336, JL252645, JL252166, JL252833, JL252748")
        print("========================")
        
    def create_widgets(self):
        """创建GUI组件"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.columnconfigure(3, weight=0)  # 进度百分比列不拉伸
        main_frame.rowconfigure(6, weight=1)  # 日志区域行号
        
        # 标题
        title_label = ttk.Label(main_frame, text=APP_SETTINGS['GUI_SETTINGS']['TITLE'], 
                               font=("Microsoft YaHei", 14, "bold"))
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 15))
        
        # 输入区域
        self.create_input_section(main_frame)
        
        # 控制按钮区域
        self.create_control_section(main_frame)
        
        # 进度条
        self.progress = ttk.Progressbar(main_frame, mode='determinate', length=400)
        self.progress.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5)
        
        # 进度百分比标签
        self.progress_var = tk.StringVar(value="")
        progress_label = ttk.Label(main_frame, textvariable=self.progress_var, font=("Microsoft YaHei", 9))
        progress_label.grid(row=3, column=3, sticky=tk.W, padx=(5, 0), pady=5)
        
        # 状态标签
        self.status_var = tk.StringVar(value="就绪")
        status_label = ttk.Label(main_frame, textvariable=self.status_var)
        status_label.grid(row=4, column=0, columnspan=3, pady=5)
        
        # 输出日志区域
        self.create_log_section(main_frame)
        
        # 结果信息区域
        self.create_result_section(main_frame)
    
    def create_input_section(self, parent):
        """创建输入设置区域"""
        input_frame = ttk.LabelFrame(parent, text="输入设置", padding="10")
        input_frame.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(0, 10))
        input_frame.columnconfigure(1, weight=1)
        
        # 数据目录选择
        ttk.Label(input_frame, text="数据目录:").grid(row=0, column=0, sticky=tk.W, pady=5)
        ttk.Entry(input_frame, textvariable=self.data_dir_var, width=50).grid(
            row=0, column=1, sticky=(tk.W, tk.E), padx=(5, 5), pady=5)
        ttk.Button(input_frame, text="浏览...", command=self.browse_data_dir).grid(
            row=0, column=2, sticky=tk.W, pady=5)
        
        # 时间范围
        ttk.Label(input_frame, text="时间范围:").grid(row=1, column=0, sticky=tk.W, pady=5)
        time_entry = ttk.Entry(input_frame, textvariable=self.time_range_var, width=30)
        time_entry.grid(row=1, column=1, sticky=tk.W, padx=(5, 5), pady=5)
        ttk.Label(input_frame, text="例如: 2025Q1-2025Q2 或 2025Q1", 
                 font=("Microsoft YaHei", 8), foreground="gray").grid(row=1, column=2, sticky=tk.W, pady=5)
        
        # 绑定输入变化事件
        self.data_dir_var.trace('w', self.on_input_change)
        self.time_range_var.trace('w', self.on_input_change)
        
        # 验证状态显示
        validation_frame = ttk.Frame(input_frame)
        validation_frame.grid(row=2, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=(10, 5))
        
        ttk.Label(validation_frame, text="检查状态:", font=("Microsoft YaHei", 9, "bold")).pack(side=tk.LEFT)
        self.validation_label = ttk.Label(validation_frame, textvariable=self.validation_status, 
                                         font=("Microsoft YaHei", 9))
        self.validation_label.pack(side=tk.LEFT, padx=(5, 0))
    
    def create_control_section(self, parent):
        """创建控制按钮区域"""
        control_frame = ttk.Frame(parent)
        control_frame.grid(row=2, column=0, columnspan=3, pady=15)
        
        # 开始处理按钮（初始状态为禁用）
        self.process_btn = ttk.Button(control_frame, text="开始处理", 
                                     command=self.start_processing,
                                     width=12, state=tk.DISABLED)
        self.process_btn.pack(side=tk.LEFT, padx=(0, 15))
        
        # 打开结果目录按钮
        self.open_result_btn = ttk.Button(control_frame, text="打开结果目录", 
                                         command=self.open_result_directory,
                                         state=tk.DISABLED,
                                         width=12)
        self.open_result_btn.pack(side=tk.LEFT, padx=(0, 15))
        
        # 清空日志按钮
        ttk.Button(control_frame, text="清空日志", 
                  command=self.clear_log,
                  width=10).pack(side=tk.LEFT)
    
    def create_log_section(self, parent):
        """创建日志区域"""
        log_frame = ttk.LabelFrame(parent, text="处理日志", padding="5")
        log_frame.grid(row=6, column=0, columnspan=4, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(10, 0))
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
        
        # 创建日志文本框
        log_settings = APP_SETTINGS['LOG_SETTINGS']
        self.log_text = scrolledtext.ScrolledText(log_frame, 
                                                 height=log_settings['HEIGHT'], 
                                                 width=80,
                                                 font=(log_settings['FONT_FAMILY'], log_settings['FONT_SIZE']))
        self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
    
    def create_result_section(self, parent):
        """创建结果信息区域"""
        result_frame = ttk.LabelFrame(parent, text="结果信息", padding="5")
        result_frame.grid(row=7, column=0, columnspan=4, sticky=(tk.W, tk.E), pady=(10, 0))
        result_frame.columnconfigure(1, weight=1)
        
        ttk.Label(result_frame, text="结果目录:").grid(row=0, column=0, sticky=tk.W, pady=2)
        ttk.Entry(result_frame, textvariable=self.result_dir_var, state="readonly").grid(
            row=0, column=1, sticky=(tk.W, tk.E), padx=(5, 0), pady=2)
    
    def set_default_values(self):
        """设置默认值"""
        # 尝试设置默认数据目录
        current_dir = os.getcwd()
        data_path = os.path.join(current_dir, "data")
        if os.path.exists(data_path):
            self.data_dir_var.set(data_path)
        
        # 初始验证
        self.validate_inputs_detailed()
    
    def browse_data_dir(self):
        """浏览选择数据目录"""
        directory = filedialog.askdirectory(
            title="选择数据目录",
            initialdir=self.data_dir_var.get() or os.getcwd()
        )
        if directory:
            self.data_dir_var.set(directory)
    
    def on_input_change(self, *args):
        """输入变化时触发验证"""
        self.validate_inputs_async()
    
    def validate_inputs_async(self):
        """异步验证输入，避免阻塞UI"""
        # 延迟验证，避免频繁触发
        if hasattr(self, '_validation_timer'):
            self.root.after_cancel(self._validation_timer)
        self._validation_timer = self.root.after(500, self.validate_inputs_detailed)
    
    def validate_inputs_detailed(self):
        """详细验证输入参数"""
        error_messages = []
        self.is_valid = True
        
        # 检查时间范围格式
        time_range = self.time_range_var.get().strip()
        if not time_range:
            error_messages.append("请输入时间范围")
            self.is_valid = False
        else:
            try:
                # 验证时间范围格式
                if '-' in time_range:
                    start, end = time_range.split('-')
                    if not is_valid_quarter_format(start.strip()) or not is_valid_quarter_format(end.strip()):
                        raise ValueError("时间范围格式错误")
                else:
                    if not is_valid_quarter_format(time_range):
                        raise ValueError("时间范围格式错误")
                
                quarters = parse_quarters(time_range)
                
                # 检查数据目录
                data_dir = self.data_dir_var.get().strip()
                if data_dir:
                    # 模式1：有数据目录，从docx提取
                    if not os.path.exists(data_dir):
                        error_messages.append("数据目录不存在")
                        self.is_valid = False
                    else:
                        # 检查季度目录是否存在
                        missing_quarters = []
                        for quarter in quarters:
                            quarter_dir = os.path.join(data_dir, quarter)
                            if not os.path.exists(quarter_dir):
                                missing_quarters.append(quarter)
                        
                        if missing_quarters:
                            error_messages.append(f"缺少季度目录: {', '.join(missing_quarters)}")
                            self.is_valid = False
                        
                        # 检查Excel查询文件
                        excel_file_path = os.path.join(data_dir, "个人剂量监测各单位编号汇总.xlsx")
                        if not os.path.exists(excel_file_path):
                            error_messages.append("缺少Excel查询文件: 个人剂量监测各单位编号汇总.xlsx")
                            self.is_valid = False
                else:
                    # 模式2：无数据目录，从历史数据读取
                    # 检查历史季度数据是否存在
                    archives_dir = os.path.join(os.getcwd(), APP_SETTINGS['QUARTERLY_ARCHIVES_DIR'])
                    missing_historical = []
                    
                    for quarter in quarters:
                        archive_file = os.path.join(archives_dir, f"{quarter}季度汇总表.csv")
                        if not os.path.exists(archive_file):
                            missing_historical.append(quarter)
                    
                    if missing_historical:
                        error_messages.append(f"缺少历史季度数据: {', '.join(missing_historical)}，请先提供数据目录生成对应的季度汇总表")
                        self.is_valid = False
                        
            except Exception as e:
                error_messages.append(f"时间范围验证出错: {str(e)}")
                self.is_valid = False
        
        # 更新验证状态显示
        if self.is_valid:
            self.validation_status.set("检查通过，可以开始处理")
            self.validation_label.config(foreground="green")
        else:
            self.validation_status.set("; ".join(error_messages))
            self.validation_label.config(foreground="red")
        
        # 更新按钮状态
        self.process_btn.config(state=tk.NORMAL if self.is_valid else tk.DISABLED)
    
    def log_message(self, message):
        """在日志区域添加消息"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()
    
    def clear_log(self):
        """清空日志"""
        self.log_text.delete(1.0, tk.END)
    
    def update_progress(self, value, text=""):
        """更新进度条
        
        Args:
            value: 进度值 (0-100)
            text: 进度文本
        """
        self.progress['value'] = value
        if text:
            self.progress_var.set(f"{value:.0f}% - {text}")
        else:
            self.progress_var.set(f"{value:.0f}%")
        self.root.update_idletasks()
    
    def reset_progress(self):
        """重置进度条"""
        self.progress['value'] = 0
        self.progress_var.set("")
        self.root.update_idletasks()
    
    def validate_for_processing(self):
        """处理前的最终验证"""
        if not self.is_valid:
            messagebox.showerror("错误", "请先解决检查失败的问题再开始处理！")
            return False
        return True
    
    def start_processing(self):
        """开始处理"""
        if not self.validate_for_processing():
            return
        
        # 在后台线程中运行处理
        self.processing_thread = threading.Thread(target=self.run_processing)
        self.processing_thread.daemon = True
        self.processing_thread.start()
    
    def run_processing(self):
        """运行处理逻辑"""
        try:
            # 禁用按钮，重置进度条
            self.root.after(0, lambda: self.process_btn.config(state=tk.DISABLED))
            self.root.after(0, lambda: self.reset_progress())
            self.root.after(0, lambda: self.status_var.set("正在处理中..."))
            
            # 创建进度回调函数
            def progress_callback(progress, text):
                self.root.after(0, lambda: self.update_progress(progress, text))
            
            # 判断处理模式
            data_dir = self.data_dir_var.get().strip()
            time_range = self.time_range_var.get().strip()
            quarters = parse_quarters(time_range)
            
            # 生成输出目录
            processor = BatchProcessor(None, progress_callback)  # 临时创建用于生成目录
            output_dir = processor.generate_output_directory(time_range)
            
            self.root.after(0, lambda: self.log_message("开始处理数据..."))
            self.root.after(0, lambda: self.log_message(f"时间范围: {time_range}"))
            self.root.after(0, lambda: self.log_message(f"输出目录: {output_dir}"))
            
            if data_dir:
                # 模式1：从数据目录的docx文件提取
                self.root.after(0, lambda: self.log_message(f"数据目录: {data_dir}"))
                self.root.after(0, lambda: self.log_message("模式：从docx文件提取数据"))
                
                # 创建批量处理器（使用数据目录中的Excel文件）
                excel_path = os.path.join(data_dir, "个人剂量监测各单位编号汇总.xlsx")
                processor = BatchProcessor(excel_path, progress_callback)
                
                # 处理数据
                quarters = processor.process_all_quarters(data_dir, time_range)
                
                # 生成所有汇总CSV文件
                result_files = processor.generate_all_summaries(quarters, output_dir, use_historical_data=False)
            else:
                # 模式2：从历史季度数据生成年度汇总
                self.root.after(0, lambda: self.log_message("模式：从历史季度数据生成年度汇总"))
                
                # 创建批量处理器
                processor = BatchProcessor(None, progress_callback)
                
                # 直接生成年度汇总表
                result_files = processor.generate_all_summaries(quarters, output_dir, use_historical_data=True)
            
            # 获取处理结果统计
            summary = processor.get_processing_summary(quarters)
            
            # 检查是否有错误
            if 'error' in result_files:
                error_msg = result_files['error']
                self.root.after(0, lambda: self.log_message(f"错误: {error_msg}"))
                self.root.after(0, lambda: self.status_var.set("处理失败"))
                self.root.after(0, lambda: messagebox.showerror("处理失败", error_msg))
                return
            
            # 更新界面
            self.root.after(0, lambda: self.result_dir_var.set(output_dir))
            self.root.after(0, lambda: self.open_result_btn.config(state=tk.NORMAL))
            self.root.after(0, lambda: self.log_message("处理完成！"))
            
            # 记录生成的文件
            if 'quarterly' in result_files:
                for quarter, file_path in result_files['quarterly'].items():
                    self.root.after(0, lambda q=quarter, f=file_path: self.log_message(f"季度汇总表: {q}季度汇总表.csv"))
            
            if 'annual' in result_files:
                self.root.after(0, lambda: self.log_message(f"年度汇总表: 年度汇总表.csv"))
            
            # 记录Excel文件
            if 'excel_files' in result_files:
                self.root.after(0, lambda: self.log_message(f"Excel文件: 共生成{len(result_files['excel_files'])}个Excel文件"))
                for excel_file in result_files['excel_files']:
                    filename = os.path.basename(excel_file)
                    self.root.after(0, lambda f=filename: self.log_message(f"  ✓ {f}"))
            
            self.root.after(0, lambda: self.log_message(f"所有结果已保存到: {output_dir}"))
            
            # 获取处理统计信息
            if data_dir:
                # 从processor获取统计信息
                summary = processor.get_processing_summary(quarters)
                self.root.after(0, lambda: self.status_var.set(f"处理完成 - {summary['total_samples']}个样品，{summary['over_limit_count']}个超标"))
                
                # 构建显示文件列表
                file_list = []
                if 'quarterly' in result_files:
                    for quarter in sorted(result_files['quarterly'].keys()):
                        file_list.append(f"{quarter}季度汇总表.csv/.xlsx")
                if 'annual' in result_files:
                    file_list.append("年度汇总表.csv/.xlsx")
                
                excel_count = len(result_files.get('excel_files', []))
                
                # 显示完成对话框
                self.root.after(0, lambda: messagebox.showinfo(
                    "处理完成", 
                    f"批量处理已完成！\n\n"
                    f"处理季度: {', '.join(quarters)}\n"
                    f"样品数量: {summary['total_samples']} 个\n"
                    f"超标样品: {summary['over_limit_count']} 个\n"
                    f"生成文件: {', '.join(file_list)}\n"
                    f"Excel文件: {excel_count} 个\n"
                    f"结果目录: {output_dir}"
                ))
            else:
                # 历史数据模式
                file_list = []
                if 'quarterly' in result_files:
                    for quarter in sorted(result_files['quarterly'].keys()):
                        file_list.append(f"{quarter}季度汇总表.csv/.xlsx")
                if 'annual' in result_files:
                    file_list.append("年度汇总表.csv/.xlsx")
                
                excel_count = len(result_files.get('excel_files', []))
                
                if len(quarters) == 1:
                    self.root.after(0, lambda: self.status_var.set("从历史数据复制季度汇总表完成"))
                else:
                    self.root.after(0, lambda: self.status_var.set("从历史数据生成汇总表完成"))
                
                # 显示完成对话框
                self.root.after(0, lambda: messagebox.showinfo(
                    "处理完成", 
                    f"从历史数据处理完成！\n\n"
                    f"处理季度: {', '.join(quarters)}\n"
                    f"生成文件: {', '.join(file_list)}\n"
                    f"Excel文件: {excel_count} 个\n"
                    f"结果目录: {output_dir}"
                ))
            
        except Exception as e:
            error_msg = f"处理过程中出错: {str(e)}"
            self.root.after(0, lambda: self.log_message(f"错误: {error_msg}"))
            self.root.after(0, lambda: self.status_var.set("处理失败"))
            self.root.after(0, lambda: messagebox.showerror("错误", error_msg))
        
        finally:
            # 恢复界面状态
            self.root.after(0, lambda: self.process_btn.config(state=tk.NORMAL))
    
    def open_result_directory(self):
        """打开结果目录"""
        result_dir = self.result_dir_var.get()
        if not result_dir or not os.path.exists(result_dir):
            messagebox.showerror("错误", "结果目录不存在！")
            return
        
        if not open_file_explorer(result_dir):
            messagebox.showerror("错误", "无法打开目录！")


def main():
    """主函数"""
    # 创建主窗口
    root = tk.Tk()
    
    # 创建应用
    app = ExtractorGUI(root)
    
    # 设置窗口居中
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    x = (root.winfo_screenwidth() // 2) - (width // 2)
    y = (root.winfo_screenheight() // 2) - (height // 2)
    root.geometry(f"{width}x{height}+{x}+{y}")
    
    # 运行主循环
    root.mainloop()


if __name__ == "__main__":
    main()
